#include "MyGraphClass.h"
#include "MyVertexClass.h"

using namespace std;

MyGraph::MyGraph(int GiveSize){
    MyVertex temp;
    int i;
    for(i=0;i<GiveSize;i++){
        VVertices.push_back(temp);
    }
}

MyGraph::~MyGraph(){

}

void MyGraph::AddConnection(int iFrom,int iTo,double dweight){
    VVertices[iFrom].ConnectTo(iTo,dweight);
    //VVertices[iFrom].ShowNext();
}

void MyGraph::ShowVertices(){
    int i;
    cout << "******************************************************" << endl;
    cout << "AFFICHAGE DU GRAPH" << endl;
    cout << "******************************************************" << endl;
    cout << "Nombre de sommets:\t" << NumberVertices() << endl;
    
    for(i=0;i<NumberVertices();i++){
        cout << "============================================" << endl;
        cout << "Sommet\t" << i << " Name: " << VVertices[i].GetName() << endl;
        cout << "---------------------" << endl;
        VVertices[i].ShowNext();
        cout << "============================================" << endl;
    }
    cout << "******************************************************" << endl;
}

void MyGraph::ExploreQueue(int FirstVertex){
    queue<int> TheQueue;
    list<int> temp;
    list<int>::iterator it;
    int i;
    
    
    TheQueue.push(FirstVertex);
    VVertices[FirstVertex].SetMarker(1);
    ShowQueue(TheQueue);
    
    
    while(TheQueue.size()>0){
        temp=VVertices[TheQueue.front()].GetNext();
        it=temp.begin();
        while(it!=temp.end()){
            if(VVertices[*it].GetMarker()==0){
                TheQueue.push(*it);
                VVertices[*it].SetMarker(1);
            }
            else{
            }
            it++;
        }
        TheQueue.pop();
        ShowQueue(TheQueue);
    }
    
    ClearMarker();
    
}
void MyGraph::ExploreQueue(){
    ExploreQueue(0);
}


void MyGraph::ClearMarker(){
    int i;
    for(i=0;i<VVertices.size();i++){
        VVertices[i].SetMarker(0);
    }
}

void MyGraph::ShowQueue(queue<int> TheQueue){
    queue<int> temp;
    temp=TheQueue;
    cout << "------------------------------------" << endl;
    cout << "Status de la file (FIFO)" << endl;
    cout << "------------------------------------" << endl;
    while(temp.size()>0){
        cout << temp.front() << "\t";
        temp.pop();
    }
    cout << endl << "------------------------------------" << endl;
}

void MyGraph::ExploreStack(int FirstVertex){
    stack<int> TheStack;
    list<int>::iterator it;
    list<int> temp;
    
    TheStack.push(FirstVertex);
    VVertices[FirstVertex].SetMarker(1);
    
    while(TheStack.size()>0){
         temp=VVertices[TheStack.top()].GetNext();
         cout << "top" << TheStack.top() << endl;
         it=temp.begin();
         while(true){
             if(it!=temp.end()){
                if(VVertices[*it].GetMarker()==0){
                    TheStack.push(*it);
                    VVertices[*it].SetMarker(1);
                    break;
                }
                it++;
             }
             else{
                TheStack.pop();
                break;
             }
         }
         
         ShowStack(TheStack);
    }
}

void MyGraph::ExploreStack(){
    ExploreStack(0);
}

void MyGraph::ShowStack(stack<int> TheStack){
    stack<int> temp;
    temp=TheStack;
    cout << "------------------------------------" << endl;
    cout << "Status de la file (FIFO)" << endl;
    cout << "------------------------------------" << endl;
    while(temp.size()>0){
        cout << temp.top() << "\t";
        temp.pop();
    }
    cout << endl << "------------------------------------" << endl;
}

int MyGraph::LoadLinks(string fname){
	int node1,node2;
	double theweight;
	ostringstream temp;
	
	ifstream fin(fname.data());
	
	
	if(fin.fail()==true){
		cout << fname << " NOT FOUND!"  << endl;
		return(-1);
	}
	while(fin.eof()==false){
		fin >> node1;
		fin >> node2;
		fin >> theweight;
		AddConnection(node1,node2,theweight);
		temp.str("");
		temp << node1;
		VVertices[node1].SetName(temp.str());
		temp.str("");
		temp << node2;
		VVertices[node2].SetName(temp.str());
	}
	return(0);
}

int MyGraph::LoadNames(string fname){
	int node;
	string thename;
	
	ifstream fin(fname.data());
	
	
	if(fin.fail()==true){
		cout << fname << " NOT FOUND!"  << endl;
		return(-1);
	}
	while(fin.eof()==false){
		fin >> node;
		fin >> thename;
		VVertices[node].SetName(thename);
	}
	return(0);
}

string MyGraph::getName(int i){
	if(i<NumberVertices()){
		return(VVertices[i].GetName());
	}
	else{
		return("Unnamed");
	}
}

int MyGraph::ProduceDotFile(){
	int i;
	ofstream fout("out.dot");
	list<int> temp;
	list<double> tempw;
	list<int>::iterator it;
	list<double>::iterator itw;
	
	
	fout << "digraph G{" << endl << "ratio=1.333;" << endl;
	
	for(i=0;i<NumberVertices();i++){
		fout << "\"" << VVertices[i].GetName() << "\"[color="<< VVertices[i].GetColor() <<"];" << endl;
	}
	
	for(i=0;i<NumberVertices();i++){
		temp	=	VVertices[i].GetNext();
		tempw	=	VVertices[i].GetWeight();
		it	=	temp.begin();
		itw	=	tempw.begin();
		while(it!=temp.end()){
			fout << "\"" << VVertices[i].GetName() << "\"->\""<< VVertices[*it].GetName() << "\" [label=" << *itw  <<"];" << endl;
			it++;
			itw++;
		}
	}
	
	fout << "}" << endl;
	
	system("dot -Tpng out.dot -o out.png");
	
	return(0);
}
int MyGraph::SortNext(){
	int i;
	for(i=0;i<NumberVertices();i++){
		VVertices[i].SortNext(true);
	}
	return(0);
}
int MyGraph::SortNext(int inode, bool Permute){
	return(VVertices[inode].SortNext(Permute));
}

int MyGraph::getNext(int inode,int nextnum){
	return(VVertices[inode].getNext(nextnum-1));
}

void MyGraph::setName(int i,string newname){
	VVertices[i].SetName(newname);
}


int MyGraph::getNextMax(int inode){
	return(VVertices[inode].GetNumberVertices());
}

double MyGraph::getNextWeight(int inode,int nextnum){
	return(VVertices[inode].getNextWeight(nextnum-1));
}
